/**
 * @file ble_rev_main.h
 * @brief
 *
 * @version 0.1
 * @date 2023-09-05
 *
 * @copyright  Copyright (c) 2020~2030 ShenZhen dingxintongchuang Technology Co., Ltd.
 * All rights reserved.
 *
 * @note          鼎新同创・智能锁
 *
 * @par 修改日志:
 * <1> 2023-09-05 v0.1 tianshidong 创建初始版本
 * *************************************************************************
 */

#ifndef _BLE_REV_MAIN_H_
#define _BLE_REV_MAIN_H_
#include "component.h"

/* 把ASCII转化为int型 */
#define ASCII_TO_INT(data, len)     \
    for (int i = 0; i < len; i++) \
        data[i] = data[i] - '0';

//#define BLE_MAX_PAYLOAD_LEN 32 // payload最大长度

#define BIND_TIMER_TIMEOUT_MS (120000) //TODO:配网时，120s不休眠


#define BLE_NONDATA_ACK_LENGTH    0x0C
#define BLE_VTS_CMD_LENGTH        0x04

#define BLE_ACKDATA_LENGTH        100

#define BLE_MESSAGE_VER           1
#define BLE_NON                   0
#define BLE_CON                   1
#define BLE_ACK                   3
/**************模组地址定义**************/
#define LKMD  0x03     // 锁控模组
#define APP   0x04     // 手机APP

////////////////////////////////////////////////////////////////
//APP下发命令
#define BLE_GET_PRODUCT_INFO      0x8071      // 查询门锁产品信息
#define BLE_DEVICE_UNBIND         0x9061     // 设备解绑
#define BLE_GET_RAND_CODE         0x8003     // 获取随机码
#define BLE_DEVICE_BIND           0x9060     // 设备绑定
#define BLE_GET_LOCK_ALL_ATTR     0x80B0     // 获取锁控所有属性
#define BLE_KEY_CHECK             0x9062     // 密钥校验

#define BLE_UNLOCK                0x8001     // 开锁
#define BLE_LOCKED                0x8002     // 关锁
#define BLE_GET_LOCK_STATUS       0x80A5     // 获取门锁状态
#define BLE_SET_ADMIN_PWD         0x8005     //设置管理员密码
#define BLE_SET_VOLUME            0x8067     //设置锁的音量
#define BLE_ADD_LOCAL_PWD         0x8015     //远程添加本地密码
#define BLE_GET_PWD_INFO          0x8017     //远程查看锁所有密码信息
#define BLE_CHANGE_ADMIN_PWD      0x8018     // 修改管理员密码
#define BLE_GET_UTC_TIME          0x9040     // 同步网络时间
#define BLE_DEL_LOCAL_PWD         0x8016     // 远程删除本地密码 TODO: 若删除成功，需要调用 8056 上报添加事件。

//指纹
#define BLE_ADD_FINGER            0x9020     // 添加指纹
#define BLE_DEL_FINGER            0x9021     // 删除指纹
#define BLE_CANCEL_ADD_FINGER     0x9022     // 取消添加指纹
#define BLE_ENROLL_FINGER_NOTIFY  0x9023     // 指纹注册进度通知

//事件相关
#define BLE_REPORT_UNLOCK_EVENT      0x8050  // 上报开锁事件
#define BLE_REPORT_LOCK_EVENT        0x8051  // 上报关锁事件
#define BLE_REPORT_LOW_POWER_EVENT   0x8052  // 低电事件
#define BLE_REPORT_UNLOCK_ERR_EVENT  0x8054  // 开锁异常事件
#define BLE_REPORT_ADD_KEY_EVENT     0x8055  // 添加钥匙通知事件
#define BLE_REPORT_DEL_KEY_EVENT     0x8056  // 删除钥匙通知事件

//卡片
#define BLE_ADD_NFC               0x9050     // 卡片录入
#define BLE_CANCEL_ADD_NFC        0x9051     // 取消卡片录入
#define BLE_ENROLL_NFC_NOTIFY     0x9052     // 卡片添加结果上报

//设置,获取相关指令
#define BLE_GET_VOLUME            0x8068     // 获取锁的音量
#define BLE_GET_POWR_VALUE        0x8064     // 获取锁端电量
#define BLE_GET_DEVICE_MODEL_AND_VERSION   0x8070 // 查询门锁型号和版本信息--和0x8071统一
#define BLE_SETTING_AUTO_LOCK_TIME         0x8095 // 设置自动闭锁时间
#define BLE_GET_AUTO_LOCK_TIME    0x8096     // 获取自动闭锁时间

/**************结构体里面的一些宏定义**************/
// 远程添加本地密码(0x8015); 开锁类型和远程查看锁所有密码信息(0x8017) 是一样的
#define PWD_TYPE_LONG_TIME        0x00       // 长期密码
#define PWD_TYPE_PERIOD           0x01       // 周期性密码
#define PWD_TYPE_TEMPORARY        0x02       // 临时密码

#define ERRNO_OK                  0x00       // 成功
#define ERRNO_PWD_ILLEGAL         0x01       // 密码不合法
#define ERRNO_NOTE_ILLEGAL        0x02       // 备注信息不合法
#define ERRNO_PWD_REPETITION      0x66       // 密码信息重复
#define ERRNO_PWD_FULL            0x67       // 数据条数已达到上限
#define ERRNO_UNKNOWN             0x68       // 未知错误 TODO:确认是否104

#define UNLOCK_FINGER             0x00       // 指纹开锁
#define UNLOCK_PWD                0x01       // 普通密码开锁
#define UNLOCK_DYNAMIC_PWD        0x02       // 动态密码开锁
#define UNLOCK_TEMPORARY_PWD      0x03       // 临时密码开锁
#define UNLOCK_CARD               0x04       // 感应卡开锁
#define UNLOCK_ELECTRONIC_KEY     0x05       // 电子钥匙开锁
#define UNLOCK_IRIS               0x06       // 虹膜开锁 iris
#define UNLOCK_FACE               0x07       // 人脸开锁
#define UNLOCK_UNKNOWN            0x08       // 未知方式开锁
#define UNLOCK_MECHANICAL_KEY     0x09       // 机械钥匙开锁
#define UNLOCK_ROMOTE             0x0A       // 远程开锁
#define UNLOCK_PERIOD_PWD         0x0B       // 周期性密码开锁
#define UNLOCK_ADMIN_PWD          0x0C       // 管理员密码开锁
#define UNLOCK_INDOOR             0x0D       // 门内开锁 
#define UNLOCK_MANUAL             0x0E       // 旋钮开锁 

//修改管理员密码(0x8018)
#define SET_SUCCESS               0x00     // 成功
#define SET_FAILED                0x01     // 失败
#define OLD_ADMINPWD_ERR          0x02     // 旧管理员密码错误
#define NEW_ADMINPWD_FORMAT_ERR   0x03     // 新密码格式错误

//指纹注册进度通知(0x9023)
#define ENROLL_SUCCESS            0x00     //注册成功
#define ENROLL_FAILED             0x01     //注册失败
#define ENROLL_TIMEOUT            0x02     //注册超时
#define ENROLL_IN_PROGRESS        0x03     //注册中

//卡片添加结果上报(0x9052)
#define NFC_ENROLL_SUCCESS        0x00     //成功
#define NFC_ENROLL_FAILED         0x01     //失败
#define NFC_ENROLL_EXIST          0x02     //卡片已存在
#define NFC_ENROLL_TIMEOUT        0x03     //录入超时

//上报关锁事件(0x8051) 关锁方式
// #define LOCKED_INDOOR             0x00       // 门内关锁
// #define LOCKED_MANUAL             0x01       // 旋钮关锁 
// #define LOCKED_OUTDOOR            0x02       // 门外关锁
// #define LOCKED_TIMING             0x03       // 定时关锁 
// #define LOCKED_ROMOTE             0x04       // 远程关锁

//=============================================================================
//命令数据结构类型
//=============================================================================
#pragma pack(1)

typedef struct
{
    // uint16_t ver :  4;    //  消息结构定义版本号。目前使用版本号固件为 1
    // uint16_t type:  2;    //  消息类型：NON（0，不需要应答的数据）、CON（1，必须要应答的数据）、ACK（3， 针对某个 CON 的应答数据）
    // uint16_t seq : 10;    // 消息序号，用于匹配应答，应答包 seq 需和请求包 seq 一致。
    uint16_t vts;
    uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
} Ble_genaral_rev_t;

typedef struct
{
    uint16_t dataLen;   //数据帧长度，从 dst_addr(包含 dst_addr)到 checksum(包含 checksum)的数据长度
    uint8_t dst_addr;   //数据目标模组地址
    uint8_t src_addr;   //数据来源模组地址
    uint32_t random_code;//通讯随机码--获取随机码指令该字段为 0x1
    //帧负载数据--按小端方式排放--结构体成员按 1 字节对齐方式排列
    struct
    {
        // uint16_t ver : 4;      //  消息结构定义版本号。目前使用版本号固件为 1
        // uint16_t type: 2;     //  消息类型：NON（0，不需要应答的数据）、CON（1，必须要应答的数据）、ACK（3， 针对某个 CON 的应答数据）
        // uint16_t seq : 10;    // 消息序号，用于匹配应答，应答包 seq 需和请求包 seq 一致。
        uint16_t vts;
        uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
        uint8_t dataBuf[BLE_ACKDATA_LENGTH];    //消息负载数据，具体长度依具体数据而定。 BLE_COMP_BUFFER_SIZE 60
		//uint16_t checksum;   //校验码(放在负载数据的最后两个字节)：CRC16 ( dataLen + dst_addr + src_addr + random_code + data )
    }Payload;
} BleAckPacket_stu_t;

typedef struct
{
	uint8_t  pwd[PWD_LEN_MAX];	//密码
	uint8_t  status;			//密钥有效状态
	uint8_t  attr;    			//钥匙属性：永久、一次性、策略……
	uint8_t  week;    			//钥匙策略：周几生效（为0表示当前策略类型为年月日策略）
	uint32_t stime;   			//钥匙策略：起始时间
	uint32_t etime;   			//钥匙策略：结束时间
	uint32_t ctime;   			//钥匙创建时间
}Ble_Password_stu_t;

typedef struct
{
	uint8_t  fpt;     //指纹ID

	uint8_t  attr;    //钥匙属性：永久、一次性、策略……
	uint8_t  week;    //钥匙策略：周几生效（为0表示当前策略类型为年月日策略）
	uint32_t stime;   //钥匙策略：起始时间
	uint32_t etime;   //钥匙策略：结束时间
	uint32_t ctime;   //钥匙创建时间
}Ble_Fpt_stu_t;

typedef struct
{
	uint8_t  card[10]; //卡片ID   CARD_LEN_MAX

	uint8_t  attr;     //钥匙属性：永久、一次性、策略……
	uint8_t  week;     //钥匙策略：周几生效（为0表示当前策略类型为年月日策略）
	uint32_t stime;    //钥匙策略：起始时间
	uint32_t etime;    //钥匙策略：结束时间
	uint32_t ctime;    //钥匙创建时间
}Ble_Card_stu_t;

/* 远程添加本地密码(0x8015) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
    uint8_t pwd_type;// 0 – 长期密码; 1 – 周期性密码 2 – 临时密码
    uint8_t period;//周期有效性:bit0~6 分别代表周日~周六是否开启，0 为关闭，1 为开启；
    uint16_t start_min;//周期性密码的起始时间，精确到分钟，如 9:00，则是 540；
    uint16_t end_min; //周期性密码的终止时间，精确到分钟；
    uint32_t start_timestamp;//周期性密码及临时密码有效期开始时间戳(精确到秒)
    uint32_t end_timestamp; //周期性密码及临时密码有效期结束时间戳(精确到秒)
    uint8_t passwd[32]; //数字密码信息，以’\0’为结束符
} Ble_keySet_stu_t;

typedef struct{
    uint16_t new_id;
    int16_t errno; // 0 - 成功 , 1 - 密码不合法, 2 - 备注信息不合法, 102 - 密码信息重复, 103 - 数据条数已达到上限, -1 - 未知错误
    uint8_t type;//0=指纹开锁、 1=普通密码开锁、 2=动态密码开锁、 3=临时密码开锁、 4=感应卡开锁、 5=电子钥匙开锁、 6=虹膜开锁、 7、 人脸开锁、 8=未知方式、 9 机械钥匙， 10=远程开锁,11=周期性密码开锁， 12=管理员密码开锁
    uint8_t pwd_type;// 0 – 长期密码; 1 – 周期性密码 2 – 临时密码
    uint8_t period;//周期有效性:bit0~6 分别代表周日~周六是否开启，0 为关闭，1 为开启；
    uint16_t start_min;//周期性密码的起始时间，精确到分钟，如 9:00，则是 540；
    uint16_t end_min; //周期性密码的终止时间，精确到分钟；
    uint32_t start_timestamp;//周期性密码及临时密码有效期开始时间戳(精确到秒)
    uint32_t end_timestamp; //周期性密码及临时密码有效期结束时间戳(精确到秒)
    uint8_t passwd[32]; //数字密码信息，以’\0’为结束符
} Ble_keySet_ack_stu_t;

/* 设置管理员密码（0x8005) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
    uint8_t passwd[32]; //数字密码信息，以’\0’为结束符
} Ble_AdminPwdSet_stu_t;

typedef struct
{
    int16_t error_code; //0 - 成功 , 1 - 密码不合法, 2 - 备注信息不合法, 102 - 密码信 息重复, 103 - 数据条数已达到上限, -1 - 未知错误
    uint16_t id;//管理员密码 id
} Ble_AdminPwdSet_ack_stu_t;

//远程查看锁所有密码信息(0x8017)
typedef struct
{
    uint8_t unlock_type; //0=指纹开锁、 1=普通密码开锁、 2=动态密码开锁、 3=临时密码开锁、4=感应 卡开锁、 5=电子钥匙开锁、
    // 6=虹膜开锁、 7、 人脸开锁、 8=未知方式、 9 机械钥匙， 10=远程开锁， 11=周期性密码开锁,12=管理员密码开锁
    uint16_t pwd_id;
}pwd_info_t;
typedef struct
{
    uint16_t id_num; //密码数量
	pwd_info_t infos[];
}Ble_GetPwdInfo_ack_stu_t;

/* 修改管理员密码（0x8018) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
    uint8_t old_password[20]; // 旧管理员密码
    uint8_t new_password[20]; // 新管理员密码
} Ble_AdminPwdChange_stu_t;


/* 同步网络时间(0x9040) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd;         // 消息命令号，标识消息用途和 data 结构。
    uint32_t utc_time; // 时间戳，精确到秒
    int16_t time_zone; // 时区
} Ble_GetUtcTime_stu_t;

/* 远程删除本地密码(0x8016) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd; // 消息命令号，标识消息用途和 data 结构。
    uint16_t id;  //要删除的密码 id
} Ble_keyDel_stu_t;

typedef struct{
    uint16_t id;      //要删除的密码 id
    int16_t ret_code; // 0 - 成功 , 1 - 失败
} Ble_keyDel_ack_stu_t;

/* 指纹注册进度通知(0x9023) */
typedef struct{
    uint8_t percentage; //指纹注册百分比
    uint8_t state; //0 – 注册成功, 1 – 注册失败, 2- 注册超时, 3 – 注册中
    uint16_t pwd_id; //指纹密码 id，如果未注册完成或注册失败则返回 0xffff，注册成功则返回指纹密码 ID
} Ble_enroll_finer_ack_stu_t;

/* 删除指纹(0x9021) */
typedef struct
{
    uint16_t vts;
    uint16_t cmd; // 消息命令号，标识消息用途和 data 结构。
    uint16_t pwd_id; //指纹密码 ID
} Ble_FingerDel_stu_t;

/* 卡片录入(0x9050) */
typedef struct{
    int16_t result; //0-成功 1-失败
    //uint32_t user_id; //用户 ID
} Ble_Nfcadd_ack_stu_t;


/* 卡片添加结果上报(0x9052) */
typedef struct{
    int16_t result; // 0 - 成功 , 1 - 失败, 2 - 卡片已存在 3 - 录入超时
    uint32_t user_id; //用户 ID
} Ble_enroll_nfc_ack_stu_t;

/* 上报开锁事件(0x8050) */
typedef struct{
    uint32_t local_timestamp;//utc
    uint32_t event_id;//事件唯一 ID 值的范围从[10000,99999]，每次上报事件 ID 要在短时 间内保证不同
    uint16_t key_id;//钥匙编号,也就每种开锁方式的唯一编号
    uint8_t unlock_type;//开锁方式
    uint8_t hijack_flag; //劫持标记。 0 未劫持， 1 已劫持， 2 无法判断。
    uint8_t unlocker_alias; //开锁者备注，若不存在，填一字节'\0'; string
    uint8_t unlocker_id;//[可选]开锁者 ID,字符串，要求带'\0'。 unlocker_id[] string
} Ble_report_unlock_event_stu_t;  
/*开锁方式取值范围：0，1，2，3，4，5，6，7，8,9,10 0=指纹开锁、1=普通密码开锁、2=动态密码开锁、
3=临时密码开锁、4=感应卡开锁、5=电子钥匙开锁、
6=虹膜开锁、7、人脸开锁、8=未知方式、9 机械钥匙，10=远程开锁, 11=周期性密码开锁,12=管理员密码
开锁， 13=门内开锁， 14=旋钮开锁*/


/* 上报关锁事件(0x8050) */
typedef struct{
    uint32_t local_timestamp;
    uint32_t event_id; //事件唯一 ID， 范围从[10000,99999]
    uint8_t lock_type; //关锁方式： 0=门内关锁 1=旋钮关锁,2=门外关锁， 3=定时关锁， 4=远程关锁
} Ble_report_locked_event_stu_t;  


//删除钥匙通知事件(0x8056) (*)
typedef struct{
    uint32_t local_timestamp;
    uint32_t event_id; //事件唯 ID
    uint16_t key_id; //钥匙编号
    uint8_t type;
    /* 0=指纹开锁、 1=普通密码开锁、 2=动态密码开锁、 3=临时密码开锁、 4=感应
    卡开锁、 5=电子钥匙开锁、 6=虹膜开锁、 7、 人脸开锁、 8=未知方式、 9 机械钥匙， 10=远程开
    锁,11=周期性密码开锁,12=管理员密码开锁， 13=门内开锁， 14=旋钮开锁*/
    uint8_t unlocker_id; //[可选]开锁者 ID,字符串， 要求带'\0'。 char unlocker_id[n]
} Ble_report_delkey_event_stu_t;


//添加钥匙通知事件(0x8055)
typedef struct{
    uint32_t local_timestamp;
    uint32_t event_id; //事件唯 ID
    uint8_t type;
    /*0=指纹开锁、 1=普通密码开锁、 2=动态密码开锁、 3=临时密码开锁、 4=感应
    卡开锁、 5=电子钥匙开锁、 6=虹膜开锁、 7、 人脸开锁、 8=未知方式、 9 机械钥匙， 10=远程开
    锁,11=周期性密码开锁, 12=管理员密码开锁， 13=门内开锁， 14=旋钮开锁*/
    uint16_t key_id; //钥匙编号
    uint8_t unlocker_id;//char unlocker_id[n]; //[可选]开锁者 ID,字符串， 要求带'\0'。
    uint32_t start_ts; //有效期起始时间戳
    uint32_t end_ts; //有效期终止时间戳
} Ble_report_addkey_event_stu_t;

//获取锁的音量(0x8068)
typedef struct
{
    uint8_t voice_volume; //语音导航音量 1 – 静音， 2 – 低， 3 – 中， 4 – 高
    uint8_t doorbell_volume; //门铃音量 1 – 静音， 2 – 低， 3 – 中， 4 – 高
}get_volume_stu_t;

//获取锁端电量(0x8064)
typedef struct
{
    int8_t battery_value; // [0 - 100] 非充电电池电量值(没有填-1)
    int8_t power_value; //[0 - 100] 充电电池电量值(没有填-1)
}get_powervalue_stu_t;

//设置自动闭锁时间(0x8095)
typedef struct
{
    uint16_t vts;
    uint16_t cmd; 
    uint16_t auto_lock_time; //0 – 关闭自动闭锁， 5 ~ 900 (s) – 自动闭锁时间
} Ble_Setting_AutoLock_Time_stu_t; 

typedef struct
{
    int8_t result; //0 – 成功， 1 – 失败
    uint16_t auto_lock_time; //0 – 关闭自动闭锁， 5 ~ 900 (s) – 自动闭锁时间
} Ble_Setting_AutoLock_Time_Ack_stu_t;

//获取自动闭锁时间 (0x8096)
typedef struct
{
    uint16_t auto_lock_time; //0 – 关闭自动闭锁， 5 ~ 900 (s) – 自动闭锁时间
} Ble_Get_AutoLock_Time_stu_t; 

#pragma pack()



// static uint8_t RevMain_get_mac_address(uint8_t *msg, uint8_t len);

#endif
